/******************************************************************************
 * Filename : lt.c
 * Copyright: Unisky, Inc
 * Created  : 2014-3-21 by lihuihui
 * Description - link tester V1.0
 * 
 ******************************************************************************/


#include "uc.h"

#include "uc_utils.h"

#define DATA_PER_BUF_MAX 1024 * 100

#define LT_MSG_INFO 801
#define LT_MSG_DATA 802
#define LT_MSG_END 803

#define LT_HASH_SIZE 1024

#define MID "123456789012"
#define LT_LINK_MAX_CNT 32

typedef struct _ltmsg_data {
	UC_U16 index;
	UC_U8 flag;
	UC_U8 interval;
	UC_U8  data[0];
} ltmsg_data_s;

typedef struct _lt_link {
	void *pUclink;
	uclink_link_info_s link_info;
}lt_link_s;

typedef struct lt_global_st {
	int if_srv;
	int port;
	UC_U32 seesion;
	int data_size;
	char filename[UC_BUF_LINE_LEN];
	UC_U16 index_recv;
	UC_U16 index_send;


	uclock_s lt_lock;

	// server
	int data_srv_recv;
	void *pUclDev;
	void *pUcl;
	int recv_end;
	UC_S64 srv_start_tick;
	int proto;
	uchash_table_s *recv_data;
	// mthash_data_s lt_hash;

	// client
	char devname[UC_BUF_LEN_SMALL];
	char ip[INET_ADDRSTRLEN];
	int link_cnt;
	UC_S64 cli_start_tick;
	lt_link_s arr_lt_link[LT_LINK_MAX_CNT];
	
} lt_global_s;

lt_global_s lt_global;

void usage()
{
	uc_p("\n\nError:<format error>, please input the correct format:\n");
	uc_p("\nClient format:\n");
	uc_p("./lt -c <server_ip>  <server_port>  <dev=ethN,wlanN,pppN,wwanN>  <file_name>\n\n");
	uc_p("Server format:\n");
	uc_p("./lt -s <port>  <protocal=0-tcp, 1-udp>\n\n");

	exit(0);
}

char *
lt_msg_type_name(UC_U32 msg_type)
{
	switch(msg_type) {
		case LT_MSG_DATA:
			return "LT_MSG_DATA";
		case LT_MSG_END:
			return "LT_MSG_END";
		case LT_MSG_INFO:
			return "LT_MSG_INFO";
	}

	return "Unknown";
}

int
lt_send_data(void *pUclDev, int type, char *buf, int len)
{	
	uclink_frame_send_s *frame = NULL;
	ltmsg_data_s *pData = NULL;
	int size_hton = 0;

	frame = (uclink_frame_send_s *)uc_malloc(sizeof(uclink_frame_send_s) + len + sizeof(ltmsg_data_s));
	if(frame == NULL) {
		uc_err("send data malloc error\n");
		return ERROR;
	}

	frame->creat_time_ms = uctime_uptime_msec();
	frame->lifetime_ms = 0;
	
	frame->msg.type = type;
	if (type == LT_MSG_DATA) {
		frame->msg.len = len + sizeof(ltmsg_data_s);
		pData = (ltmsg_data_s *)frame->msg.data;
		pData->index = htons(lt_global.index_send);
		lt_global.index_send++;
		memcpy(frame->msg.data + sizeof(ltmsg_data_s), buf, len);		
	} else if (type == LT_MSG_INFO) {
		frame->msg.len = sizeof(int);
		size_hton = htonl(lt_global.data_size);
		memcpy(frame->msg.data, &size_hton, sizeof(size_hton));
	} else {
		frame->msg.len = len;
	}
	
	//printf(">>>>>>>> send msg [type=%s], size: %d, index: %d\n", lt_msg_type_name(frame->msg.type), frame->msg.len, lt_global.index_send);

	return uclink_send_data(pUclDev, frame);
}

int
lt_srv_num_hash(UC_U16 id)
{
	return (id % LT_HASH_SIZE);
}

static int
lt_srv_buf_compare_index(uchash_table_s *pTab, uchash_node_s * pNode, void *p)
{
	uclink_frame_recv_s *pFrame = uchash_entry(pNode, uclink_frame_recv_s, node_hash);
	ltmsg_data_s *pData = (ltmsg_data_s *)pFrame->msg.data;

	if (*((UC_U16 *)p) == pData->index) {
		return ERROR;
	}
	return OK;
}

uclink_frame_recv_s *
lt_srv_buf_get_by_index(UC_U16 index)
{
	uclink_frame_recv_s *pFrame = NULL;
	uchash_node_s *pNode = NULL;
	
	pNode = uchash_walk(lt_global.recv_data, lt_srv_num_hash(index), lt_srv_buf_compare_index, &(index));
	if(pNode != NULL) {
		uchash_del(pNode, lt_global.recv_data);
		pFrame = uchash_entry(pNode, uclink_frame_recv_s, node_hash);
	}
	return pFrame;
}

int
lt_srv_buf_key(uchash_node_s *pNode, void *p)
{
	uclink_frame_recv_s *pFrame = uchash_entry(pNode, uclink_frame_recv_s, node_hash);
	ltmsg_data_s *pData = (ltmsg_data_s *)(pFrame->msg.data);

	return (lt_srv_num_hash(pData->index));
}

int
lt_srv_uclink_output(uclink_frame_recv_s *pMsg, void *pParam)
{
	char *pData = (char *)pMsg->msg.data;
	ltmsg_data_s *pMsgData = (ltmsg_data_s *)pMsg->msg.data;
	int size = 0;

	switch(pMsg->msg.type) {
		case LT_MSG_INFO:
			memcpy(&size, pData, sizeof(int));
			lt_global.data_size = ntohl(size);
			uc_p(">>>>>>  TOTAL SIZE: %d\n", lt_global.data_size);
			//lt_global.index_recv = 0;

		break;
		
		case LT_MSG_DATA:
			if (lt_global.srv_start_tick == 0) {
				lt_global.srv_start_tick = uctime_uptime_msec();
			}

			pMsgData->index = ntohs(pMsgData->index);

			uc_p("**** %d ****\n", pMsgData->index);
			
			uclock_lock(&lt_global.lt_lock);
			uchash_add(&pMsg->node_hash, lt_global.recv_data);
			uclock_unlock(&lt_global.lt_lock);			
		break;
		
		case LT_MSG_END:
			uc_p(">>>>>> END\n");			
			lt_global.recv_end = 1;
			break;
		
		default:
			uc_free(pMsg);
		break;
	}
	
	return OK;
}

int
lt_sync_notify(void *pUCLDevice, void *pParam)
{	
	uc_p("lt sync notify !\n");
	return OK;
}

int
lt_check_reg(char *mid, int client_type, char *reg_str, uclink_dev_cfg_s *pCfgDev, uclink_net_cfg_s *pCfgNet, char *reg_str_ret, int *reg_ret)
{
	*reg_ret = 0;
	sprintf(reg_str_ret, "%s", "waka waka wu wu, waka waka wu wu");


	//printf(">>>>>>  mid: %s ********\n", mid);

	strcpy(pCfgDev->name, "lt-test");
	pCfgDev->pkt_size = 1024;
	pCfgDev->if_grp_redu = 0;
	pCfgDev->protocol = lt_global.proto == 1 ? 1 : 2;
	pCfgDev->frame_buf_max = 1000;
	pCfgDev->pParam = NULL;
	pCfgNet->window_size = 128;
	pCfgNet->ack_on_tcp = 0;
	pCfgNet->udp_inv_on_off = 1;
	pCfgNet->udp_inv_default = 0;
	pCfgNet->udp_inv_min = 0;
	pCfgNet->udp_inv_max = 5;
	pCfgNet->udp_inv_step_up = 1;
	pCfgNet->udp_inv_step_down = 1;
	pCfgNet->udp_inv_adjust_level = 75;
	pCfgNet->grp_switch = 1;
	
	lt_global.pUclDev = uclink_srv_dev_get(lt_global.pUcl, mid);

	return OK;
}

void lt_server()
{
	uclink_cfg_s uclink_cfg;
	void *pUcl = NULL;
	uclink_dev_info_s dev_info;
	uclink_link_info_s link_info[UCLINK_DEV_LINK_MAX];
	int link_cnt = 0;
	UC_S64 now_tick = 0, last_tick = 0;
	uclink_frame_recv_s *pFrame = NULL;
	const char *filename= "lt_recv_data";
	int diff;
	int fd = -1;

	uc_system("rm -f %s\n", filename);
	uc_system("rm -rf /mt/data/log/link_recv.log\n");

	fd = open(filename, O_CREAT|O_WRONLY|O_APPEND, 0777);
	if (fd <= 0) {
		uc_err("open file %s, error\n", filename);
		exit(0);
	}

	lt_global.recv_data = uchash_create(LT_HASH_SIZE, lt_srv_buf_key, NULL);
	lt_global.index_recv = 0;

	memset(&uclink_cfg, 0, sizeof(uclink_cfg)); 
	uclink_cfg.pMsgtype = lt_msg_type_name;
	uclink_cfg.pOutput = lt_srv_uclink_output;
	uclink_cfg.server.pSync = lt_sync_notify;
	uclink_cfg.server.pReg = lt_check_reg;
	uclink_cfg.server.pUpdate = NULL;
	uclink_cfg.server.port = lt_global.port;

	pUcl = uclink_srv_creat(&uclink_cfg);
	if(pUcl == NULL) {
		uc_p("link init error\n");
		return;
	}
	lt_global.pUcl = pUcl;

	last_tick = now_tick = uctime_uptime_msec();
	while(1) {
		now_tick = uctime_uptime_msec();
		if (lt_global.pUclDev == NULL) {
			uclink_srv_dev_get(lt_global.pUcl, MID);
		}
		
		if (lt_global.pUclDev != NULL) {
			if (now_tick - last_tick > 5000) {
				uclink_get_info(lt_global.pUclDev, &dev_info, link_info, &link_cnt);
				if (dev_info.flow.byte_recv_ps > 0) {
					#ifdef __x86_64__
						uc_p("[%ld] >>> flow: %dKB/s, transfered: %dKB of %dKB, recv_index: %d\n", 
							now_tick, dev_info.flow.byte_recv_ps / 1024, lt_global.data_srv_recv / 1024, lt_global.data_size / 1024, lt_global.index_recv);
					#else
						uc_p("[%lld] >>> flow: %dKB/s, transfered: %dKB of %dKB, recv_index: %d\n", 
							now_tick, dev_info.flow.byte_recv_ps / 1024, lt_global.data_srv_recv / 1024, lt_global.data_size / 1024, lt_global.index_recv);
					#endif
				}
				last_tick = now_tick;
			}

			uclock_lock(&lt_global.lt_lock);
			pFrame = lt_srv_buf_get_by_index(lt_global.index_recv);
			if (pFrame != NULL) {
				lt_global.index_recv++;
			}
			uclock_unlock(&lt_global.lt_lock);
			
			if (pFrame != NULL) {
				lt_global.data_srv_recv += pFrame->msg.len - sizeof(ltmsg_data_s);
				//ucfile_append((char *)filename, (char *)pFrame->msg.data + sizeof(ltmsg_data_s), pFrame->msg.len - sizeof(ltmsg_data_s));
				write(fd, (char *)pFrame->msg.data + sizeof(ltmsg_data_s), pFrame->msg.len - sizeof(ltmsg_data_s));
				if (lt_global.data_size > 0 && lt_global.recv_end > 0) {
					if (lt_global.data_srv_recv > lt_global.data_size) {
						uc_p("[WARING] recv too much !!!\n");
					}
					if (lt_global.data_srv_recv == lt_global.data_size) {
						now_tick = uctime_uptime_msec();
						
						if (lt_global.pUclDev == NULL) {
							lt_global.pUclDev = uclink_srv_dev_get(lt_global.pUcl, MID);
						}
						if (lt_global.pUclDev != NULL) {
							lt_send_data(lt_global.pUclDev, LT_MSG_END, NULL, 0);
							uc_sleep(3000);
						}
				
						diff = (now_tick - lt_global.srv_start_tick) / 1000;
						if (diff <= 0) {
							diff = 1;
						}
						uc_p("[END] total: %dKB, spend: %d sec, avg speed: %dKB/s\n", lt_global.data_size / 1024,
							diff, (lt_global.data_size / 1024) /diff);
						close(fd);
						exit(0);
					}
				}
			} else {
				uc_sleep(50);
			}			
		} else {
			uc_sleep(1000);
		}
	}
	
}

int
lt_cli_uclink_output(uclink_frame_recv_s *pMsg, void *pParam)
{
	UC_S64 recv_end_tick = 0;
	int diff = 0;

	switch(pMsg->msg.type) {
		case LT_MSG_END:
			recv_end_tick = uctime_uptime_msec();
			diff = (int)(recv_end_tick - lt_global.cli_start_tick);
			diff = diff/1000;
			if (diff <= 0) {
				diff = 1;
			}
			uc_p("[END] send: %dKB, spend: %d sec, avg speed: %dKB/s\n", lt_global.data_size / 1024, diff, (lt_global.data_size / 1024) /diff);
			exit(0);
		break;
		
		default:
			uc_free(pMsg);
		break;
	}

	return OK;
}

enum lt_cli_stat {
	LT_CLI_STAT_INIT,
	LT_CLI_STAT_INFO,
	LT_CLI_STAT_DATA,
	LT_CLI_STAT_END,
	LT_CLI_STAT_QUIT
};

void lt_client()
{
	uclink_cfg_s uclink_cfg;
	uclink_link_cfg_s link_cfg;
	uclink_dev_info_s dev_info;
	void *pUcl = NULL;
	void *pUclDev = NULL;
	int stat = LT_CLI_STAT_INIT;
	int i = 0;
	int frame_cnt = 0;
	int pkt_cnt = 0;
	int fec_cnt = 0;
	int protocal = 0;
	int send_data_left = 0;
	int buf_size = 0;
	int fd = -1;
	int n;
	UC_S64 now_tick, last_tick;
	char *read_buf = NULL;
	int j = 0;
	int show_head = 0;
	lt_link_s *pLt_link = NULL;
	int pkt_resend_cnt = 0;
	int total_flow_s = 0;
	int total_data_flow_s_acked = 0;
	int total_flow_r = 0;
	//char file_name[UC_BUF_LEN_SMALL];
	//char data_buf[UC_BUF_LEN_SMALL];

	lt_global.index_send = 0;

	read_buf = (char *)uc_malloc(DATA_PER_BUF_MAX);
	if (read_buf == NULL) {
		uc_err("malloc read buf error\n");
		return;
	}

	memset(&uclink_cfg, 0, sizeof(uclink_cfg_s));
	uclink_cfg.pMsgtype = lt_msg_type_name;
	uclink_cfg.pOutput = lt_cli_uclink_output;
	uclink_cfg.client.dev_type = 0;
	uclink_cfg.client.p3gsend = NULL;
	uclink_cfg.client.pParam = NULL;
	sprintf(uclink_cfg.client.mid, MID);
	sprintf(uclink_cfg.client.reg_str, "%s", uclink_cfg.client.mid);

	pUcl = uclink_cli_creat(&(uclink_cfg));
	if(pUcl == NULL) {
		uc_err("lt init cli link error\n");
		return;
	}
	
	pUclDev = uclink_cli_dev_get(pUcl);
	while(1) {
		if (stat == LT_CLI_STAT_INIT) {
			for(i = 0; i < lt_global.link_cnt; i++) {
				memset(&link_cfg, 0, sizeof(uclink_link_cfg_s));
				link_cfg.link_type = UC_LINK_TYPE_ETH;
				sprintf(link_cfg.if_name, "%s_%d", lt_global.devname, i);
				uc_strncpy(link_cfg.serv_ip, lt_global.ip, sizeof(link_cfg.serv_ip));
				uc_strncpy(link_cfg.if_ip, "172.16.21.1", sizeof(link_cfg.if_ip));
				link_cfg.serv_port = lt_global.port;
				pLt_link = &(lt_global.arr_lt_link[i]);
				if(pLt_link->pUclink == NULL) { 
					pLt_link->pUclink = uclink_cli_link_add(pUclDev, &link_cfg);
				}
			}

			while(1) {
				uc_sleep(1000);
				uclink_cli_get_network(pUclDev, &frame_cnt, &pkt_cnt, &fec_cnt, &protocal, &dev_info, 0);
				if (dev_info.connected_cnt > 0) {
					break;
				}
				uc_p("wait connect to server: %s:%d\n", lt_global.ip, lt_global.port);				
			}
			
			stat = LT_CLI_STAT_INFO;
		} else if (stat == LT_CLI_STAT_INFO) {
			

			lt_send_data(pUclDev, LT_MSG_INFO, NULL, 0);
			stat = LT_CLI_STAT_DATA;

			last_tick = lt_global.cli_start_tick = uctime_uptime_msec();
		} else if (stat == LT_CLI_STAT_DATA) {
			if (strlen(lt_global.filename) > 0) {
				send_data_left = lt_global.data_size;
				fd = open(lt_global.filename, O_RDONLY);
				if (fd < 0) {
					uc_p("open file: %s, error\n", lt_global.filename);
					exit(0);
				}
				uc_p("open file: %s    >>>> \n", lt_global.filename);
				while (send_data_left > 0) {					
					now_tick = uctime_uptime_msec();
					if (now_tick - last_tick > 5000) {
						last_tick = now_tick;
						pkt_resend_cnt = 0;
						total_flow_s = 0;
						total_data_flow_s_acked = 0;
						total_flow_r = 0;
						
						show_head = 0;

						//print debug
						for(j = 0; j < lt_global.link_cnt; j++) {
							pLt_link = &(lt_global.arr_lt_link[j]);
							
							uclink_cli_link_get_info(pLt_link->pUclink, &(pLt_link->link_info));
							if(show_head <= 0) {
								show_head = 1;		
								uc_debug("   link send_pers send_pers_v recv_pers	 rto inv disp back send recv acked rs_rto rs_eack drop lst_snd lst_rsnd win pri tmpt\n");
							}
							uc_debug("%7s %9d %11d %9d %4d %3d %4d %4d %4d %4d %5d %6d %7d %4d %7d %8d %3d %3d %4d\n", 
								pLt_link->link_info.local.if_name,
								pLt_link->link_info.local.flow.byte_send_ps, 
								pLt_link->link_info.local.flow.byte_send_acked_ps, 
								pLt_link->link_info.local.flow.byte_recv_ps, 
								pLt_link->link_info.local.rtt,
								pLt_link->link_info.local.udp_inv,
								pLt_link->link_info.local.flow.pkt_dispatch,
								pLt_link->link_info.local.flow.pkt_fetchback, 
								pLt_link->link_info.local.flow.pkt_send, 
								pLt_link->link_info.local.flow.pkt_recv,
								pLt_link->link_info.local.flow.pkt_send_acked,
								pLt_link->link_info.local.flow.pkt_resend_rto,
								pLt_link->link_info.local.flow.pkt_resend_eack,
								pLt_link->link_info.local.flow.pkt_drop,
								pLt_link->link_info.local.list_link_put_cnt,
								pLt_link->link_info.local.list_link_resend_cnt,
								pLt_link->link_info.local.win_size,
								pLt_link->link_info.local.prior_val,
								pLt_link->link_info.local.if_detect);
							
								pkt_resend_cnt += pLt_link->link_info.local.list_link_resend_cnt;
								total_flow_s += pLt_link->link_info.local.flow.byte_send_ps;
								total_data_flow_s_acked += pLt_link->link_info.local.flow.byte_send_acked_ps;
								total_flow_r += pLt_link->link_info.local.flow.byte_recv_ps;

								/*sprintf(file_name, "/root/link%d_rto_eack_cnt.csv", j);
								sprintf(data_buf, "%d, %d, %d\n", 
									pLt_link->link_info.local.flow.pkt_resend_rto, pLt_link->link_info.local.flow.pkt_resend_eack, pLt_link->link_info.local.flow.pkt_resend_rto + pLt_link->link_info.local.flow.pkt_resend_eack);
								ucfile_append(file_name, data_buf, strlen(data_buf));
								*/
						}
						uclink_cli_get_network(pUclDev, &frame_cnt, &pkt_cnt, &fec_cnt, &protocal, NULL, 0);
						uc_debug(">>>>flow_s_a_r[%d_%d_%d],buf[%d-%d-%d], flow:%dKB/s, left: %dKB of %dKB <<<<\n\n\n", 
							total_flow_s, total_data_flow_s_acked, total_flow_r, frame_cnt, pkt_cnt, pkt_resend_cnt, 
							total_flow_s / 1024, send_data_left / 1024, lt_global.data_size / 1024);
					}
					
					n = read(fd, read_buf, DATA_PER_BUF_MAX < send_data_left ? DATA_PER_BUF_MAX : send_data_left);
					if (n <= 0) {
						break;
					}
					send_data_left -= n;

					while(1) {
						uclink_cli_get_network(pUclDev, &frame_cnt, &pkt_cnt, &fec_cnt, &protocal, NULL, 0);
						if (frame_cnt > 16) {
							uc_sleep(100);
							continue;
						}
						break;
					}

					lt_send_data(pUclDev, LT_MSG_DATA, read_buf, n);
				}
				close(fd);
				if (send_data_left != 0) {
					uc_err(">>>> send file error, left: %d\n", send_data_left);					
				}

			} else {
				send_data_left = lt_global.data_size;
				while (send_data_left > 0) {
					now_tick = uctime_uptime_msec();
					if (now_tick - last_tick > 5000) {
						uclink_cli_get_network(pUclDev, &frame_cnt, &pkt_cnt, &fec_cnt, &protocal, &dev_info, 5);
						uc_p(">>> flow: %dKB/s , drop: %dKB/s, ack: %dKB/s, left: %dKB of %dKB\n", 
							dev_info.flow.byte_send_ps / 1024, dev_info.flow.byte_drop_ps / 1024, 
							dev_info.flow.byte_send_acked_ps / 1024, send_data_left / 1024, lt_global.data_size / 1024);
						last_tick = now_tick;
					}
					
					uclink_cli_get_network(pUclDev, &frame_cnt, &pkt_cnt, &fec_cnt, &protocal, NULL, 0);
					if (frame_cnt > 16) {
						uc_sleep(100);
						continue;
					}
					buf_size = DATA_PER_BUF_MAX < send_data_left ? DATA_PER_BUF_MAX : send_data_left;
					send_data_left -= buf_size;
				
				
					lt_send_data(pUclDev, LT_MSG_DATA, read_buf, buf_size);
				}
			}		

			stat = LT_CLI_STAT_END;
		} else if (stat == LT_CLI_STAT_END) {
			lt_send_data(pUclDev, LT_MSG_END, NULL, 0);
			stat = LT_CLI_STAT_QUIT;
		} else if (stat == LT_CLI_STAT_QUIT) {
			uc_sleep(3000);
			uc_p("wait transfer end  ......\n");
			for(j = 0; j < lt_global.link_cnt; j++) {
					pLt_link = &(lt_global.arr_lt_link[j]);
					
					uclink_cli_link_get_info(pLt_link->pUclink, &(pLt_link->link_info));
					if(show_head <= 0) {
						show_head = 1;		
						uc_debug("   link send_pers send_pers_v recv_pers	 rto inv disp back send recv acked rs_rto rs_eack drop lst_snd lst_rsnd win pri tmpt\n");
					}
					uc_debug("%7s %9d %11d %9d %4d %3d %4d %4d %4d %4d %5d %6d %7d %4d %7d %8d %3d %3d %4d\n", 
						pLt_link->link_info.local.if_name,
						pLt_link->link_info.local.flow.byte_send_ps, 
						pLt_link->link_info.local.flow.byte_send_acked_ps, 
						pLt_link->link_info.local.flow.byte_recv_ps, 
						pLt_link->link_info.local.rtt,
						pLt_link->link_info.local.udp_inv,
						pLt_link->link_info.local.flow.pkt_dispatch,
						pLt_link->link_info.local.flow.pkt_fetchback, 
						pLt_link->link_info.local.flow.pkt_send, 
						pLt_link->link_info.local.flow.pkt_recv,
						pLt_link->link_info.local.flow.pkt_send_acked,
						pLt_link->link_info.local.flow.pkt_resend_rto,
						pLt_link->link_info.local.flow.pkt_resend_eack,
						pLt_link->link_info.local.flow.pkt_drop,
						pLt_link->link_info.local.list_link_put_cnt,
						pLt_link->link_info.local.list_link_resend_cnt,
						pLt_link->link_info.local.win_size,
						pLt_link->link_info.local.prior_val,
						pLt_link->link_info.local.if_detect);
					
						pkt_resend_cnt += pLt_link->link_info.local.list_link_resend_cnt;
						total_flow_s += pLt_link->link_info.local.flow.byte_send_ps;
						total_data_flow_s_acked += pLt_link->link_info.local.flow.byte_send_acked_ps;
						total_flow_r += pLt_link->link_info.local.flow.byte_recv_ps;

			}
			uclink_cli_get_network(pUclDev, &frame_cnt, &pkt_cnt, &fec_cnt, &protocal, NULL, 0);
			uc_debug(">>>>flow_s_a_r[%d_%d_%d],buf[%d-%d-%d], flow:%dKB/s, left: %dKB of %dKB <<<<\n\n\n", 
						total_flow_s, total_data_flow_s_acked, total_flow_r, frame_cnt, pkt_cnt, pkt_resend_cnt, 
						total_flow_s / 1024, send_data_left / 1024, lt_global.data_size / 1024);
		} else {
			uc_err("bad lt cli stat: %d\n", stat);
			exit(0);
		}		
	}

}

int
main(int argc, char *argv[])
{
	int filesz = 0;

	uc_set_coredump("/mt/data/");
	uc_p("\n=========================================\n");
	uc_p("\n*********File Transfer By Unisky**********\n");
	uc_p("\n=========================================\n");

	if (argc < 4) {
		usage();
	}


	memset(&lt_global, 0, sizeof(lt_global));
	uclock_init(&lt_global.lt_lock);
	
	if(strcmp(argv[1], "-s") == 0 && argc == 4) {
		lt_global.if_srv = 1;
		lt_global.port = atoi(argv[2]);
		lt_global.proto = atoi(argv[3]);

		uc_p("lt server: port[%d], proto[%s]\n\n", lt_global.port, lt_global.proto == 0 ? "TCP":"UCP"); 
		lt_server();
		
		uc_p("lt server exit\n");
	} else if(strcmp(argv[1], "-c") == 0 && argc >= 6){
		lt_global.if_srv = 0;
		strcpy(lt_global.ip, argv[2]);
		lt_global.port = atoi(argv[3]);
		strcpy(lt_global.devname, argv[4]);
		lt_global.link_cnt = 8;
		strcpy(lt_global.filename, argv[5]);
		
		if (strlen(lt_global.filename) > 0) {
			filesz = ucfile_size(lt_global.filename);
			if (filesz <= 0) {				
				uc_p("file is null!!!\n");
				exit(0);
			} else {
				//lt_global.data_size = lt_global.data_size < filesz ? lt_global.data_size : filesz;
				lt_global.data_size = filesz;
			}
		} else {
			uc_p("invalid filename!!!\n");
			exit(0);
		}

		uc_p("lt client: ip[%s] port[%d] dev[%s] link_cnt[%d], data_size[%d]\n\n", 
			lt_global.ip, lt_global.port, lt_global.devname, lt_global.link_cnt,
			lt_global.data_size);
		lt_client();
		
		uc_p("lt client exit\n");
	} else {
		usage();
		return ERROR;
	}

	return 0;
}
